# coding: utf-8

import os
import json
from datetime import date, datetime, timedelta

from sqlalchemy import or_
import xlwt
from flask import (
    render_template, redirect, url_for, flash,
    request, current_app, jsonify, send_file, abort
)
from flask_login import login_required, current_user

from .. import db
from ..forms import NotChoices
from . import op_bp
from app import encrypt
from app.auth.models import AdminEventStat
from app.auth.constant import AdminEvent
from app.axb.models import CallOrderForLT, SmsOrder
from app.seven_moor.models import SevenMoorRecord
from .models import (
    Area, Audio, User, Bill, Demand, UserInfo,
    UserTag, CancelAttentionUser, UserProtocol, BidCostRecord, Partic,
    UserMarketingInfo, GameExchangeReform, Voucher, UserLevelChangeLog
)
from app.ccws.models import OutBoundRecord, create_outbound_mission
from app.ccws.constant import QueueState, CallReason
from .user_forms import (
    CreateUserForm, DetailUserForm, SearchUserForm,
    UserTagForm, SearchTagsForm, SearchCancelAttentionUserForm,
    SearchBindForm,
    SearchSmsMarketingUserForm, SmsMarketingUserLevelForm,
    SearchUserProtocolForm, SearchPaidUserForm,
    SearchInviteUserForm, GameRewardForm,
    GiveVoucherForm, VoucherGiftForm, UserLevelForm
)
from .demand_forms import UserDemandForm
from .constant import (
    BillSubType, UserType,
    BillType, BillStatus, SINGLE_CHOICES, MULTIPLE_CHOICES,
    ParticStatus, FeedbackStatus, BillChnl, UserLevel,
    SmsMarketingLevel, MarketingStatus,
    TRIAL_VOUCHER_BID_POINT,
)
from ..wechat.utils import WX_TEMPLATE_FUNC_MAP
from ..wechat.models import WechatSendLog
from common.constant import VoucherStatus, VoucherStatType
from app.utils import MsgProxy

MODEL_MAP = {
    'May': User.invite_user_query,
    'July': User.invite_user_query_july,
}

ADD_TEMPLATE_MAP = {
    'May': 'user/invite_users.html',
    'July': 'user/invite_users_july.html',
}


@op_bp.route('/user_list', methods=['GET', 'POST'])
@login_required
def user_list():
    form = SearchUserForm(formdata=request.form or request.args)
    tag_form = SearchTagsForm(formdata=request.form or request.args)

    user_query = User.query.filter_by(deleted_at=0)
    url_kwargs = {}
    if form.validate():
        _, url_kwargs = form.generate_kwargs()
        user_query = User.generate_list_query_condition(
            args=url_kwargs,
            query=user_query
        )

        if form.binded_wx.data:
            user_query = user_query.filter(
                User.wx_openid != ''
            )

        # 用户标签过滤
        tag_query = None
        for key, value in tag_form.data.items():
            if str(value) == str(NotChoices[0][0]):
                continue
            url_kwargs[key] = value
            if tag_query is None:
                tag_query = UserTag.query
            # 多选类型单独处理
            if key in ['impression', 'business']:
                key = value
                value = True
            tag_query = tag_query.filter_by(**{key: value})
        if tag_query:
            tag_query = tag_query.subquery()
            user_query = user_query.join(
                tag_query, tag_query.c.user_id == User.id
            )
    page = request.args.get('page', 1, type=int)
    pagination = user_query.order_by(User.created_at.desc()).paginate(
        page, per_page=current_app.config['FLASKY_COMMENTS_PER_PAGE'],
        error_out=False)
    users = pagination.items

    return render_template(
        'user/user_list.html',
        form=form,
        tag_form=tag_form,
        users=users,
        pagination=pagination,
        url_kwargs=url_kwargs,
    )


@op_bp.route('/export/user_list', methods=['GET', 'POST'])
@login_required
def export_user_list():
    form = SearchUserForm(formdata=request.form or request.args)
    tag_form = SearchTagsForm(formdata=request.form or request.args)

    template_path = '/tmp/user_list_{}.xls'.format(datetime.now())
    book = xlwt.Workbook(encoding='utf-8')
    fields = [
        '用户ID', '手机号', '昵称', '微信昵称', '成就值', '类型',
        '性别', '省份', '城市', '公司名称', '激活', '是否拉黑',
        '认证状态', '开通省份', '汇币', '短信积分', '派单点', '成交次数'
    ]

    sheet = book.add_sheet('用户列表')

    for index, value in enumerate(fields):
        sheet.write(0, index, value)

    # write content
    user_query = User.query.filter_by(deleted_at=0)
    if form.validate():
        _, url_kwargs = form.generate_kwargs()

        user_query = User.generate_list_query_condition(
            args=url_kwargs,
            query=user_query
        )

        if form.binded_wx.data:
            user_query = user_query.filter(
                User.wx_openid != ''
            )

        # 用户标签过滤
        tag_query = None
        for key, value in tag_form.data.items():
            if str(value) == str(NotChoices[0][0]):
                continue
            url_kwargs[key] = value
            if tag_query is None:
                tag_query = UserTag.query
            # 多选类型单独处理
            if key in ['impression', 'business']:
                key = value
                value = True
            tag_query = tag_query.filter_by(**{key: value})
        if tag_query:
            tag_query = tag_query.subquery()
            user_query = user_query.join(
                tag_query, tag_query.c.user_id == User.id
            )

    data = [
        (
            i.id,
            i.mobile if i.is_engineer else encrypt(i.mobile),
            i.nickname,
            i.wxuser.nickname if i.wxuser else '',
            i.credit,
            i.type_display,
            i.gender_display,
            i.prov,
            i.city,
            i.com,
            i.active_display,
            '是' if i.black else '否',
            i.status_display,
            i.attention_areas_all_display,
            i.pack.bid_point if i.pack else 0,
            i.info_bid_count,
        ) for i in user_query.order_by(User.created_at.desc()).all()
    ]
    for index, each in enumerate(data):
        for num, value in enumerate(each):
            sheet.write(index+1, num, value)
    book.save(template_path)
    if not os.path.exists(template_path):
        abort(404)
    return send_file(template_path, as_attachment=True)


@op_bp.route('/add_user', methods=['GET', 'POST'])
@login_required
def add_user():
    """
    新建用户
    """
    form = CreateUserForm()
    demand_form = UserDemandForm()

    if form.validate_on_submit():
        # 检查用户是否存在
        user = User.query.filter_by(mobile=form.mobile.data).first()
        if user:
            flash('持有该电话号码的用户已存在，请勿重复添加')
            return render_template(
                "/user/user_add.html",
                form=form,
                demand_form=demand_form
            )

        user = User()
        form.populate_obj(user)
        user.mobile = user.mobile.strip()
        user.mobile = user.mobile.replace('-', '')

        # 处理区域ID
        area = Area.query.filter_by(name=form.city.data).first()
        if area:
            user.area_id = area.id

        db.session.add(user)
        db.session.flush()

        # 工程商写入默认标签
        if form.type.data == UserType.ENGINEER.value:
            UserTag.default_tag(user.id)

        # 新建用户后，如果有该用户的录音，同步更新Audio记录的uid
        audios = Audio.query.filter_by(mobile=user.mobile)
        for audio in audios:
            audio.uid = user.id

        # 设置回访, 增加回访记录
        if form.next_outbound.data:
            tmp_outbound_record, err = create_outbound_mission(
                mobile=user.mobile,
                call_reason=form.next_outbound_call_reason.data,
                schedule_time=form.next_outbound_schedule_time.data,
                user_id=user.id
            )
            if err:
                flash(err)
            else:
                db.session.add(tmp_outbound_record)

        # 新增项目
        if form.publish_demand.data:
            demand = Demand()
            demand_form.populate_obj(demand)
            demand.uid = user.id
            demand.area_id = user.area_id
            demand.prov = user.prov
            demand.city = user.city
            demand.addr = user.addr
            demand.status = demand_form.demand_status.data
            demand.type = demand_form.demand_type.data
            demand.remark = demand_form.demand_remark.data
            db.session.add(demand)
            db.session.flush()

            # 如果新建了项目，且没有设置回访，则自送增加次日早上10点的外呼任务
            if not form.next_outbound.data:
                tmp_outbound_record, err = create_outbound_mission(
                    mobile=user.mobile,
                    call_reason=CallReason.VISIT_CALLBACK.value,
                    user_id=user.id
                )
                if tmp_outbound_record:
                    db.session.add(tmp_outbound_record)

            flash('发布项目成功')
            return redirect(url_for('op_bp.demand_info', demand_id=demand.id))
        else:
            flash('新增用户成功')
            return redirect(url_for('op_bp.user_list'))
    else:
        if form.errors:
            flash('表单数据有误，请检查')
            print(form.errors)

    return render_template(
        "/user/user_add.html",
        form=form,
        demand_form=demand_form
    )


@op_bp.route('/user/<int:user_id>', methods=['GET'])
@login_required
def user_info(user_id):
    user = User.query.get_or_404(user_id)
    form = DetailUserForm(obj=user)
    voucher_form = VoucherGiftForm()
    user_tag = UserTag.get_by_args(user_id=user_id)
    tag_form = UserTagForm(obj=user_tag)
    form.city.choices = [(form.city.data, form.city.data)]
    form.phone_area_id.data = user.phone_area.name if user.phone_area else ''
    form.war_zone_id.data = user.war_zone.name if user.war_zone else ''
    user_info_rec = UserInfo.default_user_info(user.id)

    demand_form = UserDemandForm()

    pack_prov_ztree_data = json.dumps({})
    if user.pack:
        form.has_pack.data = True
        active_city_ids = [i.id for i in user.attention_areas]
        pack_prov_ztree_data = json.dumps(Area.make_prov_city_tree(
            active_city_ids=active_city_ids
        ))
        form.pack_bid_point.data = user.pack.bid_point

    # 读取公司简介
    form.com_summary.data = user_info_rec.com_summary
    if user.type == UserType.ENGINEER.value:
        form.next_outbound_call_reason.data = CallReason.REGULAR_CALLBACK.value
    demands = user.demands.all()
    partics = user.partics.order_by(Partic.created_at.desc()).all()
    # comments = user.comments.all()
    audios = user.audios.all()
    bills = user.bills.filter(
        Bill.sub_type.in_([
            BillSubType.BUY_PACK.value, BillSubType.GIFT_PACK.value,
            BillSubType.HALF_PACK.value
        ])
    ).order_by(Bill.created_at.desc()).all()

    # alter by zhouhl 2018-03-02 历史通话记录从seven_moor的查询
    if user.mobile:
        his_outbound_records = SevenMoorRecord.query.filter(
            or_(
                SevenMoorRecord.call_no == user.mobile,
                SevenMoorRecord.called_no == user.mobile,
                SevenMoorRecord.customer_real_number == user.mobile
            )
        ).order_by(
            SevenMoorRecord.id.desc()
        ).all()
    else:
        his_outbound_records = []

    # 计划外呼
    schedule_outbound_records = user.outbound_records.filter_by(
        queue_state=QueueState.WAITING.value
    ).order_by(
        OutBoundRecord.id.desc()
    ).all()

    # 当前外呼
    outbound_record = user.outbound_records.filter_by(
        queue_state=QueueState.HANDLING.value
    ).order_by(
        OutBoundRecord.id.desc()
    ).first()
    if outbound_record:
        form.outbound_record_id.data = outbound_record.id
        form.outbound_record_call_reason.data = \
            outbound_record.call_reason_display
        # 直接将接听的客服信息写入
        outbound_record.admin_id = current_user.id
        outbound_record.admin_nickname = current_user.nickname

    tag_form.user_id.data = user_id
    return render_template(
        "/user/user_info.html",
        user=user,
        form=form,
        demand_form=demand_form,
        demands=demands,
        partics=partics,
        # comments=comments,
        audios=audios,
        bills=bills,
        outbound_record=outbound_record,
        his_outbound_records=his_outbound_records,
        schedule_outbound_records=schedule_outbound_records,
        single_choices=SINGLE_CHOICES,
        multiple_choices=MULTIPLE_CHOICES,
        tag_form=tag_form,
        user_info=user_info_rec,
        pack_prov_ztree_data=pack_prov_ztree_data,
        voucher_form=voucher_form
    )


@op_bp.route('/edit_user/<int:user_id>', methods=['POST'])
@login_required
def edit_user(user_id):
    user = User.query.get_or_404(user_id)
    old_sms_marketing_level = user.sms_marketing_level
    form = DetailUserForm()
    demand_form = UserDemandForm()

    if form.validate_on_submit():
        # 等级变更时，写相关记录
        if current_user.is_administrator and user.level != form.level.data:
            UserLevelChangeLog.create(
                user_id=user.id,
                user_nickname=user.nickname,
                user_mobile=user.mobile,
                old_level=user.level,
                new_level=form.level.data,
                operator_id=current_user.id,
                openator_name=current_user.nickname,
            )

        # 修改为(疑似)非工程商,停止发项目短信
        if (old_sms_marketing_level != form.sms_marketing_level.data
            and form.sms_marketing_level.data in (
                    SmsMarketingLevel.NOT_ENGINEER.value,
                    SmsMarketingLevel.MAYNOT_ENGINEER.value)):
            marketing_info = UserMarketingInfo.get_or_create(user.id)
            if marketing_info:
                marketing_info.status = MarketingStatus.SUSPEND.value

        if user.is_engineer:
            user_tag_form = UserTagForm()
            user_tag = UserTag.default_tag(user_id)
            user_tag_form.populate_obj(user_tag)
        elif user.type != UserType.ENGINEER.value and form.type.data:
            UserTag.default_tag(user_id)

        old_user_level = user.level
        form.populate_obj(user)

        # 如果会员从铜牌以下升级为铜牌, 则需要发微信模板通知
        if (
            old_user_level < UserLevel.LEVEL_3.value
            and user.level == UserLevel.LEVEL_3.value
            and user.wx_openid
        ):
            UserInfo.default_user_info(user.id).level_3_notify = False
            template_code = 'USER_LEVEL_UP_NOTIFY'
            host = os.environ.get('wph_host') or request.host_url
            template_id, data, url = WX_TEMPLATE_FUNC_MAP[template_code](
                host, old_user_level, user.level, '优先抢单')
            to_send_data = [{
                'openid': user.wx_openid,
                'template_id': template_id,
                'data': data,
                'url': url
            }]
            db.session.add(WechatSendLog(
                openid=user.wx_openid,
                code=template_code,
                content=json.dumps(data, ensure_ascii=False),
                url=url,
                user_id=user.id,
                user_nickname=user.nickname,
                user_mobile=user.mobile
            ))
            current_app.wechat_producer.send(json.dumps(to_send_data))

        # 存储公司简介
        UserInfo.default_user_info(user.id).com_summary = form.com_summary.data

        # 处理area_id
        area = Area.query.filter_by(name=form.city.data).first()
        if area:
            user.area_id = area.id
        else:
            area = Area.query.filter_by(name=form.prov.data).first()
            if area:
                user.area_id = area.id

        # 含套餐信息
        if form.has_pack.data:
            if user.pack:
                user.attention_areas = Area.get_list_by_ids(
                        form.pack_prov.data).all() \
                    or Area.get_list_by_ids(
                        Area.get_city_ids(user.prov)).all()
            else:
                flash('该用户尚无套餐信息, 请先赠送一个初始套餐')
                return redirect(url_for('op_bp.user_info', user_id=user.id))

        # 设置回访, 增加回访记录
        if form.next_outbound.data:
            tmp_outbound_record, err = create_outbound_mission(
                mobile=user.mobile,
                call_reason=form.next_outbound_call_reason.data,
                schedule_time=form.next_outbound_schedule_time.data,
                try_again=True,
                user_id=user.id
            )
            if err:
                flash(err)
            else:
                db.session.add(tmp_outbound_record)

        # 外呼记录
        if form.outbound_record_id.data:
            record = OutBoundRecord.query.get(form.outbound_record_id.data)
            record.remark = form.outbound_record_remark.data
            record.admin_id = current_user.id
            record.admin_nickname = current_user.nickname

        # 发布项目
        if form.publish_demand.data:
            demand = Demand()
            demand_form.populate_obj(demand)
            demand.uid = user.id
            demand.area_id = user.area_id
            demand.prov = user.prov
            demand.city = user.city
            demand.addr = user.addr
            db.session.add(demand)
            db.session.flush()
            flash('发布项目成功')
            return redirect(url_for('op_bp.demand_info', demand_id=demand.id))
        else:
            flash('编辑成功')
            return redirect(url_for('op_bp.user_list'))
    else:
        flash('编辑出错，请检查表单数据。')
        return redirect(url_for('op_bp.user_info', user_id=user.id))


@op_bp.route('/cancel_attention_user_list', methods=['GET', 'POST'])
@login_required
def cancel_attention_user_list():
    form = SearchCancelAttentionUserForm(formdata=request.form or request.args)

    user_query = CancelAttentionUser.query.filter_by(deleted_at=0)
    url_kwargs = {}
    if form.validate():

        _, url_kwargs = form.generate_kwargs()

        user_query = CancelAttentionUser.generate_list_query_condition(
            args=url_kwargs,
            query=user_query
        )

    page = request.args.get('page', 1, type=int)
    pagination = user_query.order_by(CancelAttentionUser.id.desc()).paginate(
        page, per_page=current_app.config['FLASKY_COMMENTS_PER_PAGE'],
        error_out=False)
    users = pagination.items

    return render_template(
        'user/cancel_attention_user_list.html',
        form=form,
        users=users,
        pagination=pagination,
        url_kwargs=url_kwargs,
    )


@op_bp.route('/invite/users/<list_key>', methods=['GET', 'POST'])
@login_required
def invite_users(list_key):
    """
    拉新工程商列表
    """
    # NOTE 本次拉新活动以2018-05-01发短信开始的用户计算
    form = SearchInviteUserForm(formdata=request.form or request.args)

    user_query = MODEL_MAP[list_key](**form.data)

    page = request.args.get('page', 1, type=int)
    pagination = user_query.paginate(
        page,
        per_page=current_app.config['FLASKY_COMMENTS_PER_PAGE'],
        error_out=False)
    records = pagination.items

    url_kwargs = {key: value for key, value in form.data.items() if value}
    template_path = ADD_TEMPLATE_MAP[list_key]
    return render_template(
        template_path,
        form=form,
        records=records,
        pagination=pagination,
        sms_level_dict=SmsMarketingLevel.to_dict(),
        url_kwargs=url_kwargs,
        get_total_msg=User.total_invite_messages
    )


@op_bp.route('/export/invite/users_list/<list_key>')
@login_required
def export_invite_users_list(list_key):
    """
    导出拉新工程商列表
    """

    level_mapping = SmsMarketingLevel.to_dict()
    template_path = '/tmp/users_{}.xls'.format(datetime.now())
    book = xlwt.Workbook(encoding='utf-8')
    fields = [
        '工程商', '电话', '城市', '分级', '首次发送短信日期', '当前绑定状态',
        '发送短信总数', '推送订单次数', '进站次数', '点击抢单次数', '点击立即关注次数'
    ]

    sheet = book.add_sheet('营销用户信息')

    for index, value in enumerate(fields):
        sheet.write(0, index, value)
    # write content
    form = SearchInviteUserForm(formdata=request.form or request.args)
    user_query = MODEL_MAP[list_key](**form.data)

    data = user_query.all()
    for index, item in enumerate(data):
        values = [
            item.nickname,
            item.mobile,
            item.city,
            level_mapping.get(item.sms_marketing_level, ''),
            item.sms_marketing_first_date if list_key == 'May' else item.first_send_date,
            '是' if item.wx_openid else '否',
            item.total_send_count or 0,
            item.total_send_count or 0,
            item.view_count or 0,
            item.bid_click_count or 0,
            item.attend_click_count or 0
        ]
        for num, value in enumerate(values):
            sheet.write(index+1, num, str(value))
    book.save(template_path)
    if not os.path.exists(template_path):
        abort(404)
    return send_file(template_path, as_attachment=True)


@op_bp.route('/bind/users', methods=['GET', 'POST'])
@login_required
def bind_users():
    """
    create by ld_wu 2017-10-18
    加过好友的工程商
    """
    form = SearchBindForm(request.form or request.args)
    query = User.query
    if form.bind_date.data:
        query = query.filter_by(
            bind_date=form.bind_date.data
        )
    if form.bind_user_id.data:
        query = query.filter_by(
            bind_user_id=form.bind_user_id.data
        )
    else:
        query = query.filter(
            User.bind_user_id.__ne__(None)
        )
    page = request.args.get('page', 1, type=int)
    pagination = query.paginate(
        page,
        per_page=current_app.config['FLASKY_COMMENTS_PER_PAGE'],
        error_out=False)
    users = pagination.items
    return render_template(
        '/user/bind_users.html',
        users=users,
        form=form,
        url_kwargs=form.data
    )


@op_bp.route('/sms_marketing/user_list', methods=['GET', 'POST'])
@login_required
def sms_marketing_user_list():
    """
    add by zhouhl 2017-10-24
    有回应的短信营销工程商
    """

    form = SearchSmsMarketingUserForm(formdata=request.form or request.args)

    user_query = User.query.filter_by(
        deleted_at=0,
        sms_marketing_obj=True,
        sms_marketing_respond=True,
    ).order_by(
        User.sms_marketing_respond_datetime.desc()
    )
    url_kwargs = {}
    if form.validate():

        _, url_kwargs = form.generate_kwargs(ignore_values=(None, ''))

    user_query = User.generate_list_query_condition(
        args=url_kwargs,
        query=user_query
    )

    page = request.args.get('page', 1, type=int)
    pagination = user_query.paginate(
        page, per_page=50,
        error_out=False
    )
    users = pagination.items

    return render_template(
        'user/sms_marketing_user_list.html',
        form=form,
        users=users,
        pagination=pagination,
        url_kwargs=url_kwargs,
    )


@op_bp.route('/sms_marketing_user/<int:user_id>', methods=['GET', 'POST'])
@login_required
def sms_marketing_user(user_id):
    """
    add by zhouhl 2017-10-24
    有回应的短信营销工程商具体回应信息
    """
    form = SmsMarketingUserLevelForm(formdata=request.form)
    user = User.query.get_or_404(user_id)

    # 计划外呼
    schedule_outbound_records = user.outbound_records.filter_by(
        queue_state=QueueState.WAITING.value
    ).order_by(
        OutBoundRecord.id.desc()
    ).all()

    if form.validate_on_submit():
        # 设置工程商分级
        if form.sms_marketing_level.data:

            current_level = user.sms_marketing_level

            # 分级判定为疑似工程商及工程商时写入营销用户信息表
            if current_level == SmsMarketingLevel.UNCLASSIFIED.value:
                user.sms_marketing_level = form.sms_marketing_level.data
                if user.sms_marketing_level in (
                        SmsMarketingLevel.IS_ENGINEER.value,
                        SmsMarketingLevel.MAYBE_ENGINEER.value):
                    info = UserMarketingInfo.get_or_create(user_id)
                    if info:
                        info.status = MarketingStatus.ACTIVE.value
                        info.push_date = date.today()

        # 设置回访, 增加回访记录
        if form.next_outbound.data:
            tmp_outbound_record, err = create_outbound_mission(
                mobile=user.mobile,
                call_reason=form.next_outbound_call_reason.data,
                schedule_time=form.next_outbound_schedule_time.data,
                user_id=user.id
            )
            if err:
                flash(err)
            else:
                db.session.add(tmp_outbound_record)

        return redirect(url_for('op_bp.sms_marketing_user_list'))

    sms_orders = list(SmsOrder.query.filter_by(sender=user.mobile))
    call_orders = list(CallOrderForLT.query.filter_by(caller=user.mobile))
    form.sms_marketing_level.data = user.sms_marketing_level
    return render_template(
        'user/sms_marketing_user.html',
        form=form,
        user=user,
        schedule_outbound_records=schedule_outbound_records,
        sms_orders=sms_orders,
        call_orders=call_orders,
    )


@op_bp.route('/user/protocol_list', methods=['GET', 'POST'])
@login_required
def user_protocol_list():
    """
    created by chenhj at 2017/10/27

    """
    form = SearchUserProtocolForm(formdata=request.form or request.args)

    query = UserProtocol.query.filter_by(deleted_at=0)
    url_kwargs = {}
    if form.validate():

        _, url_kwargs = form.generate_kwargs()

        query = UserProtocol.generate_list_query_condition(
            args=url_kwargs,
            query=query
        )

    page = request.args.get('page', 1, type=int)
    pagination = query.order_by(UserProtocol.id.desc()).paginate(
        page, per_page=current_app.config['FLASKY_COMMENTS_PER_PAGE'],
        error_out=False)
    data = pagination.items

    return render_template(
        'user/user_protocol_list.html',
        form=form,
        data=data,
        pagination=pagination,
        url_kwargs=url_kwargs,
    )


@op_bp.route('/user/bid/costs/<int:user_id>')
@login_required
def user_bid_costs(user_id):
    """
    create by ld_wu 2017-11-03
    用户消费记录
    """

    query = BidCostRecord.query.filter(
        BidCostRecord.user_id == user_id
    ).order_by(
        BidCostRecord.id.desc()
    )
    user = User.get_by_id(user_id)

    page = request.args.get('page', 1, type=int)
    pagination = query.paginate(
        page, per_page=current_app.config['FLASKY_COMMENTS_PER_PAGE'],
        error_out=False)
    data = pagination.items

    return render_template(
        'user/bid_costs.html',
        data=data,
        pagination=pagination,
        user=user
    )


@op_bp.route('/user/<int:user_id>/black')
@login_required
def user_black(user_id):
    """
    created by chenhj at 2017/11/7

    """
    user = User.get_by_id(user_id)
    user.black = not user.black
    flash('操作成功')
    return redirect(url_for('op_bp.user_info', user_id=user_id))


@op_bp.route('/paid_users', methods=['GET', 'POST'])
@login_required
def paid_users():
    """
    created by chenhj at 2017/12/12
    付费用户列表
    """

    form = SearchPaidUserForm(formdata=request.form or request.args)
    url_kwargs = {}
    user_query = User.query.outerjoin(
        Partic, Partic.supplier_id == User.id
    ).filter(
        # Partic.status.in_([ParticStatus.WAITING.value, ParticStatus.SUCCEED.value]),
        User.is_internal.is_(False),
        User.is_virt.is_(False),
        User.id.in_(
            Bill.query.filter(
                Bill.type == BillType.INCOMING.value,
                Bill.sub_type.in_([BillSubType.BUY_PACK.value, BillSubType.HALF_PACK.value]),
                Bill.status == BillStatus.PAID.value,
                Bill.chnl.in_([BillChnl.ALIPAY.value, BillChnl.WEPAY.value]),
                Bill.amt > 0
            ).with_entities(
                db.func.distinct(Bill.uid)
            )
        )
    ).with_entities(
        User.id, User.nickname, User.mobile, User.prov,
        db.func.count(Partic.id).label('partic_count'),
        db.func.FROM_UNIXTIME(db.func.max(Partic.created_at)).label('max_partic_at')
    ).group_by(
        User.id
    ).order_by(
        db.func.max(Partic.created_at).desc()
    )

    if form.validate():

        _, url_kwargs = form.generate_kwargs()

        if form.partic_at_begin.data:
            user_query = user_query.filter(
                Partic.created_at >= form.partic_at_begin.data
            )
        if form.partic_at_end.data:
            user_query = user_query.filter(
                Partic.created_at <= form.partic_at_end.data
            )
        if form.provs.data:
            user_query = user_query.filter(
                User.prov.in_(tuple(form.provs.data))
            )

    page = request.args.get('page', 1, type=int)
    pagination = user_query.paginate(
        page, per_page=current_app.config['FLASKY_COMMENTS_PER_PAGE'],
        error_out=False)
    users = pagination.items
    users_list = []

    # 补上付费次数和退单次数
    # 补上付费总额
    for user in users:
        dic = user._asdict()
        tmp_bill = Bill.query.filter(
            Bill.uid == dic['id'],
            Bill.type == BillType.INCOMING.value,
            Bill.sub_type.in_([BillSubType.BUY_PACK.value, BillSubType.HALF_PACK.value]),
            Bill.status == BillStatus.PAID.value,
            Bill.chnl.in_([BillChnl.ALIPAY.value, BillChnl.WEPAY.value]),
            Bill.amt > 0
        ).all()
        dic['bill_count'] = len(tmp_bill)
        dic['bill_amt_total'] = 0
        for i in tmp_bill:
            dic['bill_amt_total'] += i.amt
        dic['feedback_count'] = Partic.query.filter(
            Partic.supplier_id == dic['id'],
            Partic.status == ParticStatus.SUCCEED.value,
            Partic.feedback_status.in_(
                [FeedbackStatus.REFUSE.value, FeedbackStatus.PASS.value]
            )
        ).count()
        users_list.append(dic)

    return render_template(
        'user/paid_user_list.html',
        users=users_list,
        pagination=pagination,
        url_kwargs=url_kwargs,
        form=form,
    )


@op_bp.route('/ajax/user_info', methods=["GET"])
@login_required
def ajax_get_user_info_by_mobile():
    mobile = request.args.get('mobile')
    res = dict(status=False)
    if mobile:
        user = User.get_by_args(mobile=mobile, deleted_at=0, black=False)
        if user:
            res = dict(
                status=True,
                user_id=user.id,
                nickname=user.nickname
            )

    return jsonify(res)


@op_bp.route('/game_reward', methods=['GET', 'POST'])
@login_required
def game_reward():
    """
    create by lina 2018-05-29
    管理用户游戏奖品兑换
    """
    form = GameRewardForm(formdata=request.form or request.args)
    game_query = GameExchangeReform.query
    if form.status.data != NotChoices[0][0]:
        game_query = game_query.filter(
            GameExchangeReform.status == form.status.data
        )

    _, url_kwargs = form.generate_kwargs()

    page = request.args.get('page', 1, type=int)
    pagination = game_query.paginate(
        page,
        per_page=current_app.config['FLASKY_COMMENTS_PER_PAGE'],
        error_out=False)
    records = pagination.items
    return render_template(
        'user/game_reward.html',
        form=form,
        pagination=pagination,
        records=records,
        url_kwargs=url_kwargs
    )


@op_bp.route('/game_reward/edit/<int:game_id>', methods=['GET', 'POST'])
@login_required
def game_reward_edit(game_id):
    """
    create by lina 2018-05-29
    修改兑换状态
    """
    game_exchange_reform = GameExchangeReform.query.get_or_404(game_id)
    game_exchange_reform.status = 1

    return redirect(url_for(
        'op_bp.game_reward'
    ))


@op_bp.route('/user_add_voucher', methods=['GET'])
@login_required
def user_add_voucher():
    """
    created by lina at 2018/07/05
    赠送代金券
    """
    args = request.args
    user = User.get_by_id(args['user_id'])
    count = int(args['count'])
    give_voucher_reason = int(args['give_voucher_reason'])
    operator_id = int(args['operator_id'])
    expiry_date = int(args['expiry_date'])
    today = date.today()

    for i in range(count):
        Voucher.create(
            user_id=user.id,
            bid_point=TRIAL_VOUCHER_BID_POINT,
            expired_date=today + timedelta(days=expiry_date),
            operator_id=operator_id,
            status=VoucherStatus.AVAILABLE.value,
            grant_date=today,
            reason=give_voucher_reason,
        )

    stat = AdminEventStat.get_by_args(
        date=today,
        event=AdminEvent.VOUCHER_GIFT.value,
        admin_id=current_user.id)
    if not stat:
        AdminEventStat.create(
            event=AdminEvent.VOUCHER_GIFT.value, admin_id=current_user.id,
            count=count
        )
    else:
        stat.count += count

    # 触发代金券统计生产者
    current_app.common_producer.send(
        json.dumps(
            dict(
                backend='voucher_stat',
                func='day_stat',
                kwargs=dict(
                    reason=give_voucher_reason,
                    voucher_stat_type=VoucherStatType.GRANT.value,
                    user_id=user.id,
                    stat_cnt=count,
                )
            )
        )
    )

    # 短信通知
    content = '已赠送您{}张价值200元无门槛代金券，立即打开“万屏汇”微信公众号免费抢单吧，过期将作废哦！回T退订'.format(count)
    if user.mobile and current_app.wph_sms_producer:
        current_app.wph_sms_producer.send(
            json.dumps({
                'mobile': user.mobile,
                'content': content,
            })
        )
    # app通知
    proxy = MsgProxy()
    proxy.im_msg_producer.app_give_voucher_notify(user_id=user.id, count=count)

    flash('赠送代金券成功')
    return jsonify(data=True)


@op_bp.route('/give_voucher_list', methods=['GET', 'POST'])
@login_required
def give_voucher_list():
    form = GiveVoucherForm(formdata=request.form or request.args)
    voucher_query = Voucher.query

    url_kwargs = {}
    if form.validate():
        _, url_kwargs = form.generate_kwargs()
        voucher_query = Voucher.generate_list_query_condition(
            args=url_kwargs,
            query=voucher_query
        )
        if form.nickname.data:
            user = User.get_by_args(nickname=form.nickname.data)
            user_id = user.id if user else 0
            voucher_query = voucher_query.filter(
                Voucher.user_id == user_id
            )

    page = request.args.get('page', 1, type=int)
    pagination = voucher_query.paginate(
        page,
        per_page=current_app.config['FLASKY_COMMENTS_PER_PAGE'],
        error_out=False)
    records = pagination.items
    return render_template(
        'user/give_voucher_list.html',
        form=form,
        page=page,
        pagination=pagination,
        records=records,
        url_kwargs=url_kwargs
    )


@op_bp.route('/export/give_voucher_list', methods=['GET', 'POST'])
@login_required
def export_give_voucher_list():
    """
    手动赠送代金券明细导出
    """
    form = GiveVoucherForm(formdata=request.form or request.args)
    template_path = '/tmp/voucher_{}.xls'.format(datetime.now())
    book = xlwt.Workbook(encoding='utf-8')
    fields = ['赠送时间', '受赠人手机号', '受赠人姓名', '赠送人', '赠送理由']
    sheet = book.add_sheet('赠送代金券明细信息')

    for index, value in enumerate(fields):
        sheet.write(0, index, value)
    # write content
    voucher_query = Voucher.query
    if form.validate():
        _, url_kwargs = form.generate_kwargs()
        voucher_query = Voucher.generate_list_query_condition(
            args=url_kwargs,
            query=voucher_query
        )

    data = [
        (
            i.grant_date.strftime('%F %T'),
            i.gifted_user.mobile if i.gifted_user.is_engineer else encrypt(i.gifted_user.mobile),
            i.gifted_user.nickname,
            i.operator.nickname if i.operator else '',
            i.reason_display,
        ) for i in voucher_query.all()
    ]
    for index, each in enumerate(data):
        for num, value in enumerate(each):
            sheet.write(index + 1, num, value)
    book.save(template_path)
    if not os.path.exists(template_path):
        abort(404)
    return send_file(template_path, as_attachment=True)


@op_bp.route('/user_level_exchange_log_list', methods=['GET', 'POST'])
@login_required
def user_level_exchange_log_list():
    form = UserLevelForm()
    change_query = UserLevelChangeLog.query
    url_kwargs = {}
    if form.validate():
        _, url_kwargs = form.generate_kwargs()
        change_query = UserLevelChangeLog.generate_list_query_condition(
            args=url_kwargs,
            query=change_query
        )
    page = request.args.get('page', 1, type=int)
    pagination = change_query.paginate(
        page,
        per_page=current_app.config['FLASKY_COMMENTS_PER_PAGE'],
        error_out=False)
    records = pagination.items
    return render_template(
        'user/user_level_exchange_log_list.html',
        form=form,
        page=page,
        pagination=pagination,
        records=records,
        url_kwargs=url_kwargs
    )
